﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using Game1942.Library.Background;
using Game1942.Library.Planes;

namespace Game1942.Library
{
    public class AircraftFactory
    {
        private List<Aircraft> units = new List<Aircraft>();
        private const int Rate = 300; //Cada cuandos ciclos inserto aviones
        private int counter = 0;
        private int groupCounter;
        private List<CazaGroup> groups = new List<CazaGroup>();
        private Point lastGroupUnitPosition;
        private const int groupsNumber = 3;
        private bool insertingCazaGroup = false;
        private Caza lastCaza;
        private int counterGroup;

        public AircraftFactory()
        {
            
        }

        public void InitializeAtLevel(int level)
        {
            if (level < 1 || level > 6)
            {
                throw new InvalidOperationException("The level must be between 1 and 6.");
            }
            XmlDocument xDoc = new XmlDocument();
            xDoc.Load("Xml/LevelEnemies.xml");
            
            var numberOfUnits = (XmlElement) xDoc.GetElementsByTagName("level")[level-1];

            var nUnits = int.Parse(numberOfUnits.GetElementsByTagName("CazaGroups")[0].InnerText);
            for (int i = 0; i < nUnits; i++)
            {
                groups.Add(new CazaGroup());
            }
            nUnits = int.Parse(numberOfUnits.GetElementsByTagName("Bombers")[0].InnerText);
            for (int i = 0; i < nUnits; i++)
            {
                units.Add(new Bomber());
            }
            nUnits = int.Parse(numberOfUnits.GetElementsByTagName("CivilPlanes")[0].InnerText);
            for (int i = 0; i < nUnits; i++)
            {
                units.Add(new CivilPlane());
            }
            nUnits = int.Parse(numberOfUnits.GetElementsByTagName("Explorers")[0].InnerText);
            for (int i = 0; i < nUnits; i++)
            {
                units.Add(new Explorer());
            }
            nUnits = int.Parse(numberOfUnits.GetElementsByTagName("ImprovedCazas")[0].InnerText);
            for (int i = 0; i < nUnits; i++)
            {
                units.Add(new ImprovedCaza());
            }
            nUnits = int.Parse(numberOfUnits.GetElementsByTagName("Planes")[0].InnerText);
            for (int i = 0; i < nUnits; i++)
            {
                units.Add(new Plane());
            }
            nUnits = int.Parse(numberOfUnits.GetElementsByTagName("PoliceChoppers")[0].InnerText);
            for (int i = 0; i < nUnits; i++)
            {
                units.Add(new PoliceChopper());
            }
            nUnits = int.Parse(numberOfUnits.GetElementsByTagName("GuidePlanes")[0].InnerText);
            for (int i = 0; i < nUnits; i++)
            {
                units.Add(new GuidePlane());
            }
        }

        public void RequestInsertEnemies()
        {
            InsertGroups();
            InsertEnemies();
        }

        private void InsertGroups()
        {
            var noGroupsRemaining = (groups.Count == 0);
            if (noGroupsRemaining) return;
            
            if (!ReferenceEquals(lastCaza, null))   //If it is not the first unit of the group
            {
                if ((lastCaza.ActualPosition.Y < Constants.Caza.Width) && lastCaza.Alive)
                {
                    return;
                }
                
            }
            else
            {   //Delay
                counterGroup++;
                if (counterGroup != Rate) return;
                counterGroup = 0;
            }

            var caza = groups.First().Next();
            if (caza == null)   //the current group is empty
            {
                groups.RemoveAt(0);
                lastCaza = null;
                lastGroupUnitPosition = null;
                return;
            }

            if (lastGroupUnitPosition == null)      //If it is the first unit of the group
            {
                var random = new Random(DateTime.Now.Millisecond);
                var xAxis = random.Next(0, Constants.Screen.Width/2);
                lastGroupUnitPosition = new Point(xAxis, 0);
            }
            
            caza.SetPosition(lastGroupUnitPosition);
            Driver.Instance.AddEnemy(caza);
            Driver.Instance.AddLiveUnit(caza, caza.Dimension.X, caza.Dimension.Y, "Planes/Caza");
            
            lastCaza = caza;
        }

        private void InsertEnemies()
        {
            if (counter != Rate)
            {
                counter++;
                return;
            }
            counter = 0;
            var random = new Random(DateTime.Now.Millisecond);
            for (int i = 0; i < groupsNumber && units.Count != 0; i++)
            {
                var index = random.Next(0, units.Count);
                var unit = units[index];
                unit.SetPosition(new Point(random.Next(0, Constants.Screen.Width - 100), 0));
                Driver.Instance.AddEnemy(unit);
                Driver.Instance.AddLiveUnit(unit, unit.Dimension.X, unit.Dimension.Y, "Planes/" + unit.GetType().Name);
                units.RemoveAt(index);
            }
        }

        public bool IsEmpty()
        {
            return ((units.Count == 0) && (groups.Count == 0));
        }
    }
}
